#include <stdio.h>
#include <stdlib.h>
#include <ijpege_common.h>
#include <ijpege_qt.h>
#include <ijpege_ht.h>

static char dht_sel[] = {0x00, 0x10, 0x01, 0x11};

typedef enum {			/* JPEG marker codes */
    M_SOF0  = 0xc0,
    M_SOF1  = 0xc1,
    M_SOF2  = 0xc2,
    M_SOF3  = 0xc3,

    M_SOF5  = 0xc5,
    M_SOF6  = 0xc6,
    M_SOF7  = 0xc7,

    M_JPG   = 0xc8,
    M_SOF9  = 0xc9,
    M_SOF10 = 0xca,
    M_SOF11 = 0xcb,

    M_SOF13 = 0xcd,
    M_SOF14 = 0xce,
    M_SOF15 = 0xcf,

    M_DHT   = 0xc4,

    M_DAC   = 0xcc,

    M_RST0  = 0xd0,
    M_RST1  = 0xd1,
    M_RST2  = 0xd2,
    M_RST3  = 0xd3,
    M_RST4  = 0xd4,
    M_RST5  = 0xd5,
    M_RST6  = 0xd6,
    M_RST7  = 0xd7,

    M_SOI   = 0xd8,
    M_EOI   = 0xd9,
    M_SOS   = 0xda,
    M_DQT   = 0xdb,
    M_DNL   = 0xdc,
    M_DRI   = 0xdd,
    M_DHP   = 0xde,
    M_EXP   = 0xdf,

    M_APP0  = 0xe0,
    M_APP1  = 0xe1,
    M_APP2  = 0xe2,
    M_APP3  = 0xe3,
    M_APP4  = 0xe4,
    M_APP5  = 0xe5,
    M_APP6  = 0xe6,
    M_APP7  = 0xe7,
    M_APP8  = 0xe8,
    M_APP9  = 0xe9,
    M_APP10 = 0xea,
    M_APP11 = 0xeb,
    M_APP12 = 0xec,
    M_APP13 = 0xed,
    M_APP14 = 0xee,
    M_APP15 = 0xef,

    M_JPG0  = 0xf0,
    M_JPG13 = 0xfd,
    M_COM   = 0xfe,

    M_TEM   = 0x01,

    M_ERROR = 0x100
} JPEG_MARKER;

void ijpege_write_header(ijpege_nal_t *nal, int width,int height, int quality, bool ql_en_user, uint8_t *qmem_table_user)
{
    int i, j;
    uint8_t *ptr = nal->p_payload;
    uint8_t *tmp_ptr = NULL;

    nal->i_payload = 0;

    /*************** SOI *****************/
    *ptr++ = 0xff;
    *ptr++ = M_SOI;
    /************** DQT --0 **************/
    *ptr++ = 0xff;
    *ptr++ = M_DQT;
    /************* Lq=64*2+3 *************/
    *ptr++ = 0x0;
    *ptr++ = 0x43;
    /************* Pq=0 Tq=0 *************/
    *ptr++ = 0x0;
    /************* Qk ********************/
    if (ql_en_user) {
        tmp_ptr = qmem_table_user;
    } else {
        tmp_ptr = (uint8_t *)&qt[quality][0];
    }
    for (i=0; i<64; i++) {
	    *ptr++ = *tmp_ptr++;
    }
    /************** DQT --1 *************/
    *ptr++ = 0xff;
    *ptr++ = M_DQT;
    /************** Lq=64*2+3 ***********/
    *ptr++ = 0x0;
    *ptr++ = 0x43;
    /************** Pq=0 Tq=1 ***********/
    *ptr++ = 0x1;
    /************* Qk ********************/
    for (i=0; i<64; i++)
	*ptr++ = *tmp_ptr++;
    /************* SOF ***************/
    *ptr++ = 0xff;
    *ptr++ = M_SOF0;
    /************* Lf=17 ***************/
    *ptr++ = 0x0;
    *ptr++ = 0x11;
    /********* P=8 --> 8-bit sample ******/
    *ptr++ = 0x8;
    /************* Y=height ***************/
    *ptr++ = (height & 0xff00)>>8;
    *ptr++ = height & 0xff;
    /************* X=width ***************/
    *ptr++ = (width & 0xff00)>>8;
    *ptr++ = width & 0xff;
    /***** Nf=3 (number of components) ******/
    *ptr++ = 0x3;
    /************* C1 --> Y **************/
    *ptr++ = 0x1;
    /************* H=2,V=2 **************/
    *ptr++ = 0x22;
    /************* Tq --> QT0 **************/
    *ptr++ = 0x0;
    /************* C2 --> U **************/
    *ptr++ = 0x2;
    /************* H=1,V=1 **************/
    *ptr++ = 0x11;
    /************* Tq --> QT1 **************/
    *ptr++ = 0x1;
    /************* C3 --> V **************/
    *ptr++ = 0x3;
    /************* H=1,V=1 **************/
    *ptr++ = 0x11;
    /************* Tq --> QT1 **************/
    *ptr++ = 0x1;

    /**************** DHT **************/
    for (j=0; j<4; j++) {
	*ptr++ = 0xff;
	*ptr++ = M_DHT;
	//Lh
	int size = ht_size[j];
	*ptr++ = (size & 0xff00)>>8;
	*ptr++ = size & 0xff;
	//Tc Th
	*ptr++ = dht_sel[j];
	//Li
	for (i=0; i<16; i++) {
	    *ptr++ = ht_len[j][i];
	}
	//Vij
	for (i=0; i<16; i++){
	    int m;
	    for(m=0; m<ht_len[j][i]; m++) {
		*ptr++ = ht_val[j][i][m];
	    }
	}
    }

    /************** SOS ****************/
    *ptr++ = 0xff;
    *ptr++ = M_SOS;
    //Ls = 12
    *ptr++ = 0x0;
    *ptr++ = 0xc;
    //Ns
    *ptr++ = 0x3;
    //Cs1 - Y
    *ptr++ = 0x1;
    //Td, Ta
    *ptr++ = 0x0;
    //Cs2 - U
    *ptr++ = 0x2;
    //Td, Ta
    *ptr++ = 0x11;
    //Cs3 - V
    *ptr++ = 0x3;
    //Td, Ta
    *ptr++ = 0x11;
    //Ss
    *ptr++ = 0x0;
    //Se
    *ptr++ = 0x3f;
    //Ah, Al
    *ptr++ = 0x0;
    nal->i_payload = ptr - nal->p_payload;
}

void ijpege_write_tail(ijpege_nal_t *nal)
{
	uint8_t *ptr = nal->p_payload + nal->i_payload;

	*ptr++ = 255;
	*ptr++ = 217;
	nal->i_payload += 2;
}
